package database

import (
	"fmt"
	models "huijing_mall/internal/database/models"
	"huijing_mall/shared/kernel/hmErrors"

	"gorm.io/gorm/schema"

	loggers "huijing_mall/pkg/logger"
	"time"

	"gorm.io/gorm/logger"

	mysqlCfg "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

// 先连接到系统数据库（如mysql）来创建目标数据库
func createDatabaseIfNotExists(cfg *mysqlCfg.Config) error {
	// 临时修改配置，连接到mysql系统数据库
	tempCfg := *cfg
	tempCfg.DBName = "mysql" // 或者 "information_schema"

	dsn := tempCfg.FormatDSN()
	tempDB, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		return fmt.Errorf("连接系统数据库失败: %w", err)
	}

	defer func() {
		if sqlDB, err := tempDB.DB(); err == nil {
			sqlDB.Close()
		}
	}()

	// 创建目标数据库
	sql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", cfg.DBName)
	if err := tempDB.Exec(sql).Error; err != nil {
		return fmt.Errorf("创建数据库失败: %w", err)
	}

	return nil
}

// 主连接函数
func InitDB(cfg *mysqlCfg.Config) *gorm.DB {
	// 先创建数据库（如果不存在）
	if err := createDatabaseIfNotExists(cfg); err != nil {
		panic(hmErrors.ErrSystem("创建数据库尝试失败或已存在: " + err.Error()))
		// 这里不直接返回错误，因为数据库可能已经存在
	}

	// 连接目标数据库
	dsn := cfg.FormatDSN()
	// 定义全局命名策略
	namingStrategy := schema.NamingStrategy{
		TablePrefix:   "",   // 表名前缀（如user表→t_user）
		SingularTable: true, // 表名单数化（默认是复数，如users→user）
		NameReplacer:  nil,  // 自定义字段名替换规则（可选）
	}
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger:         logger.Default.LogMode(logger.Info),
		NamingStrategy: namingStrategy,
	})
	if err != nil {
		panic(hmErrors.ErrSystem(fmt.Sprintf("获取数据库连接失败: %v", err)))
	}

	// 配置连接池
	sqlDB, err := db.DB()
	if err != nil {
		panic(hmErrors.ErrSystem(fmt.Sprintf("获取底层数据库连接失败: %v", err)))
	}

	sqlDB.SetMaxOpenConns(100)          // 最大打开连接数
	sqlDB.SetMaxIdleConns(10)           // 最大空闲连接数
	sqlDB.SetConnMaxLifetime(time.Hour) // 连接最大生命周期

	// 注册逻辑：ModelType 为 UserType，创建函数返回 &User{}
	// 第一步：批量注册所有模型（供 NewModelCRUD 使用）
	for _, m := range models.ModelToRegister {
		models.RegisterModel(m.Type, m.Creator)
	}

	// 迁移报表
	err = models.InitAutoMg(db)
	if err != nil {
		panic(hmErrors.ErrSystem(fmt.Sprintf("迁移报表失败: %v", err)))
	}
	// 使用loggers记录一条日志
	loggers.Info("initialize a Mysql database success")
	return db
}
